#include "PinHoleCamera.h"
#include "Ray.h"
#include "trax.hpp"
#include "atUtil.h"

namespace AtomTrace{

    PinHoleCamera::PinHoleCamera()
    {
        this->Init();
    }

    void PinHoleCamera::Init()
    {
        imgWidth = 128;
        imgHeight = 128;
        focalDst = 1.0f;
        fovy = 0.194f; // tan(22 degree)

        position.Set(0.0f, 0.0f, 1.0f);//Vector3::UNIT_Z;
        dir.Set(0.0f, 0.0f, -1.0f); // -Vector3::UNIT_Z;
        up.Set(0.0f, 1.0f, 0.0f); //Vector3::UNIT_Y;
    }

    void PinHoleCamera::UpdateCamParameter()
    {
        float wf = static_cast<float>(imgWidth);
        float hf = static_cast<float>(imgHeight);
        float aspectR = wf/hf;
        float hv = focalDst * fovy; // should be tan(fovy);
        float hu = hv * aspectR;

        //Vector3 dir = (lookat-position).GetNormalize();
        dir.Normalize();
        Vector3 right = (dir.Cross(up)).GetNormalize();
        up = (right.Cross(dir)).GetNormalize();

        //printf("position: [%f, %f, %f]\n", position[0], position[1], position[2]);
        //printf("dir: [%f, %f, %f]\n", dir[0], dir[1], dir[2]);
        //printf("up: [%f, %f, %f]\n", up[0], up[1], up[2]);

        dx = right * hu * 2.0f / wf;
        dy = up * hv * 2.0f / hf;

        Vector3 lookCent = position + dir * focalDst;
        //printf("LookCent[%f, %f, %f]\n", lookCent[0], lookCent[1], lookCent[2]);
        blPix = lookCent - dx * (wf*0.5f+0.5f) - dy * (hf*0.5f+0.5f);
        //printf("blPix[%f, %f, %f]\n", blPix[0], blPix[1], blPix[2]);
        //printf("dx[%f, %f, %f]\n", dx[0], dx[1], dx[2]);
        //printf("dy[%f, %f, %f]\n", dy[0], dy[1], dy[2]);

    }

    const Ray PinHoleCamera::CastRay(int pix) const
    {
        int ix = 0; //
        int iy = 0; //

        ix = pix % imgWidth;
        iy = pix / imgWidth;
        
        
        printf("ix, iy: %d, %d\n", ix, iy);
        return this->CastRay(ix, iy);
    }

    const Ray PinHoleCamera::CastRay(float ix, float iy) const
    {
        Ray res;
        res._dir  = blPix + dx * ix + dy * iy - position;
        res._dir.Normalize();
        res._o = position;
//printf("res.dir[%f, %f, %f]\n", res._dir[0], res._dir[1], res._dir[2]);
        return res;
    }

    const Ray PinHoleCamera::CastRay(int ix, int iy) const
    {
        return this->CastRay(static_cast<float>(ix), static_cast<float>(iy));
    }

}// namespace AtomTrace
